/**
 * 中文队列数据结构封装 (zh-queue.js)
 * 支持队列的基本操作、链式调用、迭代器
 * 中文方法命名 + JSDoc 参数提示
 */

class 队列 {
  /**
   * 构造函数 - 创建队列实例
   * @param {Array} [初始数据=[]] 初始队列元素数组
   */
  constructor(初始数据 = []) {
    this._数据 = [...初始数据];
  }

  /**
   * 获取队列数据数组的副本
   * @returns {Array} 队列数据的副本数组
   */
  取值() {
    return [...this._数据];
  }

  /**
   * 入队 - 添加元素到队尾
   * @param {...*} 元素 要入队的元素
   * @returns {队列} 返回this以支持链式调用
   */
  入队(...元素) {
    this._数据.push(...元素);
    return this;
  }

  /**
   * 出队 - 移除并返回队首元素
   * @returns {*} 队首元素，如果队列为空则返回undefined
   */
  出队() {
    return this._数据.shift();
  }

  /**
   * 查看队首元素但不移除
   * @returns {*} 队首元素，如果队列为空则返回undefined
   */
  查看队首() {
    return this._数据[0];
  }

  /**
   * 查看队尾元素但不移除
   * @returns {*} 队尾元素，如果队列为空则返回undefined
   */
  查看队尾() {
    return this._数据[this._数据.length - 1];
  }

  /**
   * 获取队列中元素数量
   * @returns {number} 队列的大小
   */
  大小() {
    return this._数据.length;
  }

  /**
   * 判断队列是否为空
   * @returns {boolean} 队列是否为空
   */
  是否为空() {
    return this._数据.length === 0;
  }

  /**
   * 清空队列中的所有元素
   * @returns {队列} 返回this以支持链式调用
   */
  清空() {
    this._数据 = [];
    return this;
  }

  /**
   * 创建当前队列的深拷贝
   * @returns {队列} 新的队列实例
   */
  克隆() {
    return new 队列(this._数据);
  }

  /**
   * 将队列转换为字符串
   * @param {string} [分隔符=', '] 元素分隔符
   * @returns {string} 转换后的字符串
   */
  转字符串(分隔符 = ', ') {
    return this._数据.join(分隔符);
  }

  /**
   * 遍历队列中所有元素
   * @param {Function} 回调 遍历回调函数，接收(元素,索引,数组)参数
   * @returns {队列} 返回this以支持链式调用
   */
  遍历(回调) {
    for (let i = 0; i < this._数据.length; i++) {
      回调(this._数据[i], i, this._数据);
    }
    return this;
  }

  /**
   * 查找指定元素在队列中的索引
   * @param {*} 元素 要查找的元素
   * @returns {number} 元素索引，未找到则返回-1
   */
  查找索引(元素) {
    return this._数据.indexOf(元素);
  }

  /**
   * 判断队列是否包含指定元素
   * @param {*} 元素 要检查的元素
   * @returns {boolean} 是否包含该元素
   */
  包含(元素) {
    return this._数据.includes(元素);
  }

  /**
   * 获取指定索引位置的元素
   * @param {number} 索引 元素索引
   * @returns {*} 对应位置的元素，如果索引无效则返回undefined
   */
  获取(索引) {
    if (索引 < 0 || 索引 >= this._数据.length) {
      return undefined;
    }
    return this._数据[索引];
  }

  /**
   * 批量将多个元素入队
   * @param {Array} 元素数组 要入队的元素数组
   * @returns {队列} 返回this以支持链式调用
   */
  批量入队(元素数组) {
    return this.入队(...元素数组);
  }

  /**
   * 批量出队指定数量的元素
   * @param {number} 数量 要出队的元素数量
   * @returns {Array} 出队的元素数组
   */
  批量出队(数量) {
    if (数量 >= this._数据.length) {
      const 所有元素 = [...this._数据];
      this.清空();
      return 所有元素;
    }
    
    const 结果 = [];
    for (let i = 0; i < 数量; i++) {
      结果.push(this.出队());
    }
    return 结果;
  }

  /**
   * 对队列中每个元素执行映射操作，返回新队列
   * @param {Function} 回调 映射函数，接收(元素,索引)参数
   * @returns {队列} 新的队列实例
   */
  映射(回调) {
    const 新数据 = this._数据.map((元素, 索引) => 回调(元素, 索引));
    return new 队列(新数据);
  }

  /**
   * 过滤队列中元素，返回满足条件的元素组成的新队列
   * @param {Function} 回调 过滤函数，接收(元素,索引)参数
   * @returns {队列} 新的队列实例
   */
  过滤(回调) {
    const 新数据 = this._数据.filter((元素, 索引) => 回调(元素, 索引));
    return new 队列(新数据);
  }

  /**
   * 对队列中元素执行归约操作
   * @param {Function} 回调 归约函数，接收(累加器,元素,索引)参数
   * @param {*} [初始值] 初始累加值
   * @returns {*} 归约结果
   */
  归约(回调, 初始值) {
    return this._数据.reduce((累加器, 元素, 索引) => 回调(累加器, 元素, 索引), 初始值);
  }

  /**
   * 对队列中元素进行排序，返回新队列
   * @param {Function} [比较函数] 排序比较函数
   * @returns {队列} 新的队列实例
   */
  排序(比较函数) {
    const 新数据 = [...this._数据].sort(比较函数);
    return new 队列(新数据);
  }

  /**
   * 在队列数据上执行自定义操作
   * @param {Function} 操作 接收数据数组的操作函数
   * @returns {队列|*} 新的队列实例或操作结果
   */
  执行(操作) {
    const 结果 = 操作(this._数据);
    if (Array.isArray(结果)) {
      return new 队列(结果);
    }
    return this;
  }

  /**
   * 获取队列中的最大值
   * @param {Function} [比较函数] 自定义比较函数
   * @returns {*} 最大值，如果队列为空则返回undefined
   */
  最大值(比较函数) {
    if (this.是否为空()) return undefined;
    if (!比较函数) {
      return Math.max(...this._数据);
    }
    return this._数据.reduce((最大值, 当前值) => 
      比较函数(当前值, 最大值) > 0 ? 当前值 : 最大值
    );
  }

  /**
   * 获取队列中的最小值
   * @param {Function} [比较函数] 自定义比较函数
   * @returns {*} 最小值，如果队列为空则返回undefined
   */
  最小值(比较函数) {
    if (this.是否为空()) return undefined;
    if (!比较函数) {
      return Math.min(...this._数据);
    }
    return this._数据.reduce((最小值, 当前值) => 
      比较函数(当前值, 最小值) < 0 ? 当前值 : 最小值
    );
  }

  /**
   * 迭代器实现（先进先出顺序）
   * @yields {*} 队列中的元素
   */
  *[Symbol.iterator]() {
    // 默认按队列顺序迭代（FIFO）
    for (const 元素 of this._数据) {
      yield 元素;
    }
  }

  /**
   * 反向迭代器（后进先出顺序）
   * @yields {*} 队列中的元素
   */
  *反向迭代() {
    for (let i = this._数据.length - 1; i >= 0; i--) {
      yield this._数据[i];
    }
  }

  /** 静态方法 */

  /**
   * 静态方法：创建空队列
   * @static
   * @returns {队列} 空队列实例
   */
  static 创建() {
    return new 队列();
  }

  /**
   * 静态方法：从数组创建队列
   * @static
   * @param {Array} 数组 源数组
   * @returns {队列} 队列实例
   */
  static 从数组(数组) {
    return new 队列(数组);
  }

  /**
   * 静态方法：合并多个队列
   * @static
   * @param {...队列} 队列列表 要合并的队列实例
   * @returns {队列} 合并后的新队列实例
   */
  static 合并(...队列列表) {
    const 所有数据 = [];
    for (const 队列实例 of 队列列表) {
      所有数据.push(...队列实例.取值());
    }
    return new 队列(所有数据);
  }

  /**
   * 静态方法：判断对象是否是队列实例
   * @static
   * @param {*} 对象 要检查的对象
   * @returns {boolean} 是否是队列实例
   */
  static 是队列(对象) {
    return 对象 instanceof 队列;
  }

  /**
   * 静态方法：创建优先队列
   * @static
   * @param {Function} [比较函数=(a,b)=>a-b] 优先级比较函数
   * @returns {队列} 优先队列实例
   */
  static 创建优先队列(比较函数 = (a, b) => a - b) {
    const 优先队列 = new 队列();
    
    // 重写入队方法，保持队列有序
    const 原入队 = 优先队列.入队;
    优先队列.入队 = function(...元素) {
      原入队.apply(this, 元素);
      // 插入后排序，保证队首是优先级最高的元素
      this._数据.sort(比较函数);
      return this;
    };
    
    return 优先队列;
  }

  /**
   * 静态方法：检查节点间的循环依赖
   * @static
   * @param {*} 节点 起始节点
   * @param {Function} 依赖函数 获取节点依赖的函数
   * @returns {boolean} 是否存在循环依赖
   */
  static 检查循环依赖(节点, 依赖函数) {
    const 访问中 = new Set();
    const 已访问 = new Set();
    
    function 检查(当前节点) {
      if (访问中.has(当前节点)) return true; // 发现循环
      if (已访问.has(当前节点)) return false; // 已检查过
      
      访问中.add(当前节点);
      const 依赖列表 = 依赖函数(当前节点);
      
      for (const 依赖 of 依赖列表) {
        if (检查(依赖)) return true;
      }
      
      访问中.delete(当前节点);
      已访问.add(当前节点);
      return false;
    }
    
    return 检查(节点);
  }
}



// CommonJS 导出

  module.exports = {
    队列,
    default: 队列
  };
  module.exports.队列 = 队列;


// ES 模块导出
// export { 队列 };
// export default 队列;